﻿// See https://aka.ms/new-console-template for more information
using Demos.DesignPatterns._01_Singleton;
using Demos.DesignPatterns._02_FactoryMethod;
using Demos.DesignPatterns._03_AbstractFactory;
using Demos.DesignPatterns._05_建造者模式.Services;
using Demos.DesignPatterns._06_策略模式;
using Demos.DesignPatterns._07_适配器模式;
using Demos.DesignPatterns._08_桥接模式;
using Demos.DesignPatterns._09_组合模式;
using Demos.DesignPatterns._10_装饰器模式;
using Demos.DesignPatterns._11_外观模式;
using Demos.DesignPatterns._12_享元模式;
using Demos.DesignPatterns._13_代理模式;
using Demos.DesignPatterns._14_解释器模式;
using Demos.DesignPatterns._15_模板方法;
using Demos.DesignPatterns._16_责任链模式;
using Demos.DesignPatterns._17_命令模式;
using Demos.DesignPatterns._18_迭代器模式;
using Demos.DesignPatterns._19_中介者模式;
using Demos.DesignPatterns._20_备忘录模式;
using Demos.DesignPatterns._21_观察者模式;
using Demos.DesignPatterns._22_状态模式;
using Demos.DesignPatterns._23_访问者模式;

Console.WriteLine("Hello, World!");

#region 单例模式测试

//01 单例测试
Console.WriteLine("..........单例测试 Begin....................................");

// 获取购物车服务实例
var cartService = ShoppingCartService.Instance;
// 添加商品
cartService.AddToCart(new CartItem
{
    ProductId = 1,
    ProductName = "iPhone 13",
    Price = 7999,
    Quantity = 1
});
cartService.AddToCart(new CartItem
{
    ProductId = 2,
    ProductName = "AirPods Pro",
    Price = 1499,
    Quantity = 2
});

//创建另一个购物车服务实例
var cartService2 = ShoppingCartService.Instance;
Console.WriteLine($"两个购物车实例对象是否相同：{ReferenceEquals(cartService, cartService2)}");

//多线程测试：
Parallel.For(0, 2, i =>
{
    var threadCart = ShoppingCartService.Instance;
    threadCart.AddToCart(new CartItem
    {
        ProductId = 100 + i,
        ProductName = $"测试商品{i}",
        Price = 100 * (i + 1),
        Quantity = i + 1
    });
    // 显示购物车
    cartService.DisplayCart();
});
Console.WriteLine("..........单例测试 End....................................");
#endregion

#region 工厂方法模式

Console.WriteLine("..........工厂方法模式....................................");
// 创建支付工厂
PaymentFactory paymentFactory = new AlipayFactory();
paymentFactory.ProcessPayment(200.75m);

paymentFactory = new WechatPayFactory();
paymentFactory.ProcessPayment(150.25m);

#endregion

#region 抽象工厂

Console.WriteLine("..........抽象工厂模式....................................");
// 使用示例
Console.WriteLine("\n处理国内订单:");
var domesticFactory = new DomesticPaymentFactory();
var domesticProcessor = new MyPaymentProcessor(domesticFactory);
domesticProcessor.ProcessOrder(300.50m);

Console.WriteLine("\n处理国际订单:");
var internationalFactory = new InternationalPaymentFactory();
var internationalProcessor = new MyPaymentProcessor(internationalFactory);
internationalProcessor.ProcessOrder(150.75m);

#endregion

#region 建造者模式

Console.WriteLine("..........建造者模式 Begin....................................");

// 1. 直接使用建造者
var builder = new StandardOrderBuilder();
var order = builder.SetOrderInfo("ORD20230001", DateTime.Now, "待支付")
                           .SetCustomer("CUST001", "张三", "zhangsan@example.com")
                           .AddItem("P001", "iPhone 14", 6999, 1)
                           .AddItem("P002", "AirPods Pro", 1299, 1)
                           .SetShipping("顺丰快递", "北京市海淀区", "张三", "13800138000")
                           .SetPayment("微信支付", 8298, "TXN20230001")
                           .SetDiscount("双十一优惠", 300)
                           .SetInvoice("增值税发票", "张三", "1234567890")
                           .Build();
Console.WriteLine("=== 直接使用建造者创建的订单 ===");
order.DisplayOrderInfo();

Console.WriteLine("..........建造者模式 End....................................");

#endregion

#region 策略模式

Console.WriteLine("..........策略模式 Begin....................................");
// 创建购物车并添加商品
var cart = new ShoppingCart();
//cart.AddItem(1001, "iPhone 14", 6999, 1);
cart.AddItem(1002, "AirPods Pro", 1299, 1);

// 1. 不使用折扣
cart.SetDiscountStrategy(new NoDiscount());
cart.DisplayCart();

Console.WriteLine("\n应用不同折扣策略:");

// 2. 使用10%折扣
Console.WriteLine("使用10%折扣");
cart.SetDiscountStrategy(new PercentageDiscount(10));
cart.DisplayCart();

// 3. 使用满1000减200
Console.WriteLine("使用满1000减200折扣");
cart.SetDiscountStrategy(new ThresholdDiscount(1000, 200));
cart.DisplayCart();

// 4. 使用会员折扣(金卡15%，银卡10%，普通5%)
Console.WriteLine("使用会员折扣(金卡15%，银卡10%，普通5%)");
cart.SetDiscountStrategy(new MembershipDiscount(15, 10, 5));
cart.DisplayCart();


// 动态切换策略示例
Console.WriteLine("\n动态切换策略示例:");
var strategies = new Dictionary<string, IDiscountStrategy>
{
    ["双十一"] = new PercentageDiscount(20),
    ["618"] = new ThresholdDiscount(300, 50),
    ["会员日"] = new MembershipDiscount(20, 15, 10),
    ["无活动"] = new NoDiscount()
};

Console.WriteLine("..........策略模式 End....................................");
#endregion

#region 适配器模式

Console.WriteLine("..........适配器模式 Begin....................................");

// 使用支付宝支付
var alipayService = new AlipayService();
var alipayAdapter = new AlipayAdapter(alipayService);
var alipayProcessor = new PaymentProcessor(alipayAdapter);
Console.WriteLine("测试支付宝支付:");
alipayProcessor.ExecutePayment("ALIPAY_MERCHANT_001", 500m, "CNY");
alipayProcessor.CheckStatus("TRX_20230001");


// 使用PayPal支付
var paypalService = new PaypalService();
var paypalAdapter = new PayPalAdapter(paypalService);
var paypalProcessor = new PaymentProcessor(paypalAdapter);
Console.WriteLine("\n测试PayPal支付:");
paypalProcessor.ExecutePayment("user@example.com", 100m, "USD");
paypalProcessor.CheckStatus("PAYPAL_20230001");


// 支持货币自动转换
Console.WriteLine("\n测试跨币种支付:");
paypalProcessor.ExecutePayment("user@example.com", 700m, "CNY"); // 自动转换为100 USD
alipayProcessor.ExecutePayment("ALIPAY_MERCHANT_001", 100m, "USD"); // 自动转换为700 CNY


Console.WriteLine("..........适配器模式 End....................................");

#endregion

#region 桥接模式


Console.WriteLine("..........桥接模式 Begin....................................");
// 创建物流公司实例
var sf = new SFExpress();
var dhl = new DHLlogistics();

// 国内陆运订单（顺丰）
var groundShipping = new GroundShipping(sf);
groundShipping.PrepareShipment();
groundShipping.ExecuteShipping();
groundShipping.ShowTracking(sf.CreateWaybill());
groundShipping.CompleteShipping();
Console.WriteLine("\n切换国际物流公司处理同一运输方式");
groundShipping.SwitchCompany(dhl);
groundShipping.PrepareShipment();
groundShipping.ExecuteShipping();
groundShipping.CompleteShipping();

// 国际空运订单（DHL）
var arShipping = new OceanShipping(dhl);
arShipping.PrepareShipment();
arShipping.ExecuteShipping();
arShipping.CompleteShipping();

// 海运集装箱（DHL）
var oceanShipping = new OceanShipping(dhl);
oceanShipping.PrepareShipment();
oceanShipping.ExecuteShipping();
oceanShipping.CompleteShipping();

Console.WriteLine("..........桥接模式 End....................................");
#endregion

#region 组合模式


Console.WriteLine("..........组合模式 Begin....................................");
//创建分类结构
var electronics = new ProductCategory("电子产品");

var phones = new ProductCategory("手机");
phones.Add(new Product("iPhone 13", 6999));
phones.Add(new Product("iPhone 13 Pro", 7999));

var computers = new ProductCategory("电脑");
computers.Add(new Product("MacBook Pro", 9999));
computers.Add(new Product("联想Thinkbook14+", 5999));

var gamingLaptops = new ProductCategory("游戏本");
gamingLaptops.Add(new Product("ROG Strix G15", 7999));
gamingLaptops.Add(new Product("Alienware m15", 8999));

var accessories = new ProductCategory("配件");
accessories.Add(new Product("AirPods Pro", 1299));
accessories.Add(new Product("Magic Mouse", 599));

//组合分类
electronics.Add(phones);
electronics.Add(computers);
electronics.Add(accessories);

//显示分类结构
electronics.Display(1);

//计算总价
Console.WriteLine($"\n总价值: {electronics.GetPrice():C}");


Console.WriteLine("..........组合模式 End....................................");
#endregion

#region 装饰器模式
Console.WriteLine("..........装饰器模式 Begin....................................");

ICoffee _coffee = new SimpleCoffee();
Console.WriteLine($"基础咖啡订单：{_coffee.GetDescription()}");
Console.WriteLine($"价格：{_coffee.GetCost():C}");

// 添加牛奶
_coffee = new MilkDecorator(_coffee);
Console.WriteLine($"\n加牛奶后的订单：{_coffee.GetDescription()}");
Console.WriteLine($"价格：{_coffee.GetCost():C}");
_coffee = new MochaDecorator(_coffee);
Console.WriteLine($"\n加摩卡后的订单：{_coffee.GetDescription()}");
Console.WriteLine($"价格：{_coffee.GetCost():C}");


Console.WriteLine("..........装饰器模式 End....................................");
#endregion

#region 外观模式

Console.WriteLine("..........外观模式 Begin....................................");

var theater = new HomeTheaterFacade();

theater.WatchMovie("The Shawshank Redemption");

theater.EndMovie();

#endregion

#region 享元模式

Console.WriteLine("..........享元模式 Begin....................................");

var priticleFactory = new ParticleFactory();
// 创建10个粒子（实际只创建2种类型）
for (int i = 0; i < 10; i++)
{
    var type = (i % 2 == 0)
        ? priticleFactory.GetParticleType("火焰", "红")  // 复用类型
        : priticleFactory.GetParticleType("冰晶", "蓝"); // 复用类型

    type.Draw(Random.Shared.Next(100), Random.Shared.Next(100));  // 外部状态
}

Console.WriteLine("..........享元模式 End....................................");

#endregion

#region 代理模式

Console.WriteLine("..........代理模式 Begin....................................");

ICartService shopCartService = new ShopCachedCartProxyService(new DatabaseCartService());
// 用户操作购物车
var userId = "user_1001";
var item1 = new ShopCartItem { ProductId = "prod_2001", ProductName = "iPhone 14", Price = 6999, Quantity = 1 };
var item2 = new ShopCartItem { ProductId = "prod_2002", ProductName = "AirPods Pro", Price = 1299, Quantity = 2 };
Console.WriteLine("=== 第一次添加商品 ===");
shopCartService.AddToCart(userId, item1);

Console.WriteLine("\n=== 第二次添加商品（应命中缓存）===");
shopCartService.AddToCart(userId, item2);

Console.WriteLine("\n=== 获取购物车 ===");
var _shopcart = shopCartService.GetCart(userId);
Console.WriteLine($"用户 {_shopcart.UserId} 的购物车总价：{_shopcart.CartTotal:C}");

Console.WriteLine("\n=== 清空购物车 ===");
shopCartService.ClearCart(userId);


Console.WriteLine("..........代理模式 End....................................");

#endregion

#region 解释器模式

Console.WriteLine("..........解释器模式 Begin....................................");

// 创建解释器上下文
var context = new Dictionary<string, bool>
{
    ["A"] = true,
    ["B"] = false,
    ["C"] = true
};
// 构建表达式 (A AND B) OR (A AND C)
var expr = new OrExpression(
    new AndExpression(new VariableExpression("A"), new VariableExpression("B")),
    new AndExpression(new VariableExpression("A"), new VariableExpression("C"))
);
// 解释执行
var result = expr.Interpret(context);
Console.WriteLine($"表达式解释结果：(A AND B) OR (A AND C) = {result}");

// 第二种表达式 (A OR B) AND (A OR C)
var expr2 = new AndExpression(
    new OrExpression(new VariableExpression("A"), new VariableExpression("B")),
    new OrExpression(new VariableExpression("A"), new VariableExpression("C"))
);
var result2 = expr2.Interpret(context);
Console.WriteLine($"表达式解释结果：(A OR B) AND (A OR C) = {result2}");

Console.WriteLine("..........解释器模式 End....................................");

#endregion

#region 模板方法

Console.WriteLine("..........模板方法 End....................................");
Console.WriteLine("处理国内订单");
TOrderProcessor _torder = new TDomesticOrderProcessor();
_torder.ProcessOrder();

Console.WriteLine("处理国际订单");
TOrderProcessor _torder2 = new TInternationalOrderProcessor();
_torder2.ProcessOrder();

Console.WriteLine("..........模板方法 End....................................");

#endregion

#region 责任链模式

Console.WriteLine("..........责任链模式 End....................................");

// 创建责任链
var managerApprove = new ManagerApprover();
var directorApprove = new DirectorApprover();
var ceoApprove = new CEOApprover();
// 设置责任链顺序
managerApprove.SetNext(directorApprove);
directorApprove.SetNext(ceoApprove);

// 处理不同金额审批，交由责任链处理，从最小审批人开始
managerApprove.ProcessRequest(new PurchaseRequest(600, "办公用品"));
managerApprove.ProcessRequest(new PurchaseRequest(2000, "办公电脑"));
managerApprove.ProcessRequest(new PurchaseRequest(10000, "办公家具"));

Console.WriteLine("..........责任链模式 End....................................");

#endregion

#region 命令模式

Console.WriteLine("..........命令模式 Begin....................................");

// 创建命令接收者
var light = new Light();
var remote = new RemoteControl();

//设置并执行命令
remote.SetCommand(new LightOnCommand(light));
remote.ExecuteCommand();

//撤销执行
remote.CancelCommand();


// 设置并执行关灯命令
remote.SetCommand(new LightOffCommand(light));
remote.ExecuteCommand();  // 输出：灯已关闭

// 撤销操作
remote.CancelCommand();    // 输出：灯已打开

Console.WriteLine("..........命令模式 End....................................");
#endregion

#region 迭代器模式

Console.WriteLine("..........迭代器模式 Begin....................................");

var shelf = new BookShelf(3);
shelf[0] = new Book("设计模式");
shelf[1] = new Book("代码整洁之道");
shelf[2] = new Book("重构");

var iterator = shelf.CreateIterator();

while (iterator.HasNext())
{
    var book = iterator.Next();
    Console.WriteLine($"书名：{book.Title}");
}
Console.WriteLine("..........迭代器模式 End....................................");

#endregion

#region 中介者模式

Console.WriteLine("..........中介者模式 Begin....................................");

var chatRoom = new ChatRoom();

var alice = new MsgUser("Alice", chatRoom);
var bob = new MsgUser("Bob", chatRoom);
var john = new MsgUser("John", chatRoom);

chatRoom.AddMsgUser(alice);
chatRoom.AddMsgUser(bob);
chatRoom.AddMsgUser(john);

alice.Send("Hello, Bob!");
Console.WriteLine("--------------------------");
bob.Send("Hi, Alice!");
Console.WriteLine("--------------------------");
john.Send("Hello, everyone!");

Console.WriteLine("..........中介者模式 End....................................");
#endregion

#region 备忘录模式

Console.WriteLine("..........备忘录模式 Begin....................................");

var editor = new TextEditor();
var history = new EditorHistory();

//编辑并保存状态
editor.Content = "第一版本内容";
history.Push(editor.Save());

//准备修改前保存当前状态，以便撤销
editor.Content = "第二版本内容";
history.Push(editor.Save());

if (history.CanUndo)
{
    editor.Restore(history.Pop());
    Console.WriteLine($"当前内容1：{editor.Content}");
}
// 再次撤销
if (history.CanUndo)
{
    editor.Restore(history.Pop());
    Console.WriteLine($"当前内容2：{editor.Content}");
}

Console.WriteLine("..........备忘录模式 End....................................");

#endregion

#region 观察者模式

Console.WriteLine("..........观察者模式 Begin....................................");
//创建订单服务主题
var orderService = new TOrderService("OT202504010001");
//创建并注册观察者
var userNotification = new UserNotificationService();
var inventorySystem = new InventorySystem();
orderService.Attach(userNotification);
orderService.Attach(inventorySystem);

// 模拟订单状态变化
orderService.UpdateOrderStatus(OrderStatus.Paid);
orderService.UpdateOrderStatus(OrderStatus.Shipped);
orderService.UpdateOrderStatus(OrderStatus.Delivered);

//移除观察者
orderService.Detach(inventorySystem);

Console.WriteLine("..........观察者模式 End....................................");
#endregion

#region 状态模式

Console.WriteLine("..........状态模式 Begin....................................");
var _order = new Order("ORDER-1001");
//处理订单
_order.Process();
//发货
_order.Ship();
//取消订单
_order.Cancel();  //此时取消会失败，已发货不能取消
//订单配送
_order.Deliver();

//第二种情况
Console.WriteLine("第二种情况: 处理订单ORDER-1002");
var _order2 = new Order("ORDER-1002");
_order2.Process(); // 处理订单
_order2.Cancel();  // 取消订单
_order2.Ship();    // 尝试发货（应失败）

Console.WriteLine("..........状态模式 End....................................");
#endregion

#region 访问者模式

Console.WriteLine("..........访问者模式 Begin....................................");
//创建购物车
var cart1 = new ShopCart();
cart1.AddProduct(new RegularProduct("iPhone 13", 6999, 1)); //普通商品不打折
cart1.AddProduct(new DiscountedProduct("AirPods Pro", 1299, 1099, 1));//折扣商品
cart1.AddProduct(new GiftCard("生日礼品卡", 500));//礼品卡

//打印收据
Console.WriteLine("\n购物清单：");

var receiptPrinter = new ReceiptPrinter();
cart1.Process(receiptPrinter);


var priceCalculator = new PriceCalculator();

cart1.Process(priceCalculator);


Console.WriteLine($"\n总价：{priceCalculator.TotalPrice:C}");


Console.WriteLine("..........访问者模式 End....................................");

#endregion